﻿using DotNetCommon.Extensions;
using NUnit.Framework;
using Shouldly;

namespace DotNetCommon.Test.Extensions.TypeExtensions
{
    [TestFixture]
    public class CheckingTypeIsParentOrAssignableFrom
    {
        [Test]
        public void Run()
        {
            typeof(MyClassBase).IsParentOrAssignableFrom<MyClassBase>().ShouldBeTrue();
            typeof(MyClassBase).IsParentOrAssignableFrom<MyClassA>().ShouldBeTrue();
            typeof(MyClassBase).IsParentOrAssignableFrom<IMyInterface>().ShouldBeFalse();

            typeof(MyClassA).IsParentOrAssignableFrom<MyClassBase>().ShouldBeFalse();
            typeof(MyClassA).IsParentOrAssignableFrom<MyClassA>().ShouldBeTrue();
            typeof(MyClassB).IsParentOrAssignableFrom<MyClassA>().ShouldBeFalse();
            typeof(MyClassA).IsParentOrAssignableFrom<MyClassB>().ShouldBeTrue();

            typeof(IMyInterface).IsParentOrAssignableFrom<IMyInterface>().ShouldBeTrue();
            typeof(MyClassC).IsParentOrAssignableFrom<IMyInterface>().ShouldBeFalse();
            typeof(IMyInterface).IsParentOrAssignableFrom<MyClassC>().ShouldBeTrue();
            typeof(MyClassD).IsParentOrAssignableFrom<IMyInterface>().ShouldBeFalse();
            typeof(MyClassA).IsParentOrAssignableFrom<IMyInterface>().ShouldBeFalse();

            typeof(IMyInterface).IsParentOrAssignableFrom<MyClassBase>().ShouldBeFalse();
            typeof(MyClassD).IsParentOrAssignableFrom<MyClassBase>().ShouldBeFalse();
            typeof(MyClassD).IsParentOrAssignableFrom<MyClassC>().ShouldBeFalse();

            typeof(MyStructA).IsParentOrAssignableFrom<MyStructA>().ShouldBeTrue();
            typeof(MyStructB).IsParentOrAssignableFrom<IMyInterface>().ShouldBeFalse();
            typeof(MyStructB).IsParentOrAssignableFrom<MyStructA>().ShouldBeFalse();
            typeof(MyStructA).IsParentOrAssignableFrom<MyStructB>().ShouldBeFalse();
        }

        private class MyClassBase { }
        private class MyClassA : MyClassBase { }
        private class MyClassB : MyClassA { }
        private interface IMyInterface { }
        private class MyClassC : IMyInterface { }
        private class MyClassD : MyClassA, IMyInterface { }
        private struct MyStructA { }
        private struct MyStructB : IMyInterface { }
    }
}
